package org.dromara.web.CssUtil.payUtil;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 反射工具类
 */
public class ReflectUtil {

    public static Logger logger = LoggerFactory.getLogger(ReflectUtil.class);

    public static String generateGetMethod(String fieldName){
        char firstChar = fieldName.charAt(0);
        String firstStr = String.valueOf(firstChar);
        return "get" + firstStr.toUpperCase() + fieldName.substring(1, fieldName.length());
    }

    public static Object getFieldValue(String fieldName, Object obj) throws RuntimeException{
        String getMethodName = generateGetMethod(fieldName);
        Class<?> clazz = obj.getClass();
        try {
//            Method declaredMethod = clazz.getDeclaredMethod(getMethodName, new Class[0]);
//            return declaredMethod.invoke(obj, new Object[0]);
        	Method declaredMethod = MethodUtils.getAccessibleMethod(clazz, getMethodName, new Class[0])  ;
        	return declaredMethod.invoke(obj, new Object[0]);

//        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
//            logger.error("反射获取字段值失败，没有找到该字段的get方法", e);
//            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            logger.error("反射获取字段值失败，该字段的get方法无法访问", e);
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            logger.error("反射获取字段值失败", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取类的私有字段，排除final或static字段
     * @param clazz
     * @return
     */
    public static List<String> getPrivateFields(Class<?> clazz){
        return getPrivateFields(clazz, null);
    }

    /**
     * 获取类的私有字段，排除final或static字段
     * @param clazz
     * @param excludeFieldList 指定需排除的字段
     * @return
     */
    public static List<String> getPrivateFields(Class<?> clazz, List<String> excludeFieldList){
        Field[] declaredFields = FieldUtils.getAllFields(clazz);
        List<String> fieldNameList = new ArrayList<String>();
        for (Field field : declaredFields) {
            int modifiers = field.getModifiers();
            if(Modifier.isFinal(modifiers)){
                continue;
            }
            if(!Modifier.isPrivate(modifiers)){
                continue;
            }
            if(Modifier.isStatic(modifiers)){
                continue;
            }
            String fieldName = field.getName();
            if(CollectionUtils.isNotEmpty(excludeFieldList) && excludeFieldList.contains(fieldName)){
                continue;
            }
            fieldNameList.add(fieldName);
        }
        // 去重
        HashSet<String> h = new HashSet<String>(fieldNameList);
        fieldNameList.clear();
        fieldNameList.addAll(h);
        return fieldNameList;

    }

}
